{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('skylake', 'skylake', 'sapphire', 'ice', 'ice')"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from usearch.index import Index\n",
    "\n",
    "f64_support = Index(ndim=256, metric=\"cos\", dtype=\"f64\").hardware_acceleration\n",
    "f32_support = Index(ndim=256, metric=\"cos\", dtype=\"f32\").hardware_acceleration\n",
    "f16_support = Index(ndim=256, metric=\"cos\", dtype=\"f16\").hardware_acceleration\n",
    "i8_support = Index(ndim=256, metric=\"cos\", dtype=\"i8\").hardware_acceleration\n",
    "b1_support = Index(ndim=256, metric=\"hamming\", dtype=\"b1\").hardware_acceleration\n",
    "\n",
    "f64_support, f32_support, f16_support, i8_support, b1_support"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: faiss-cpu in /home/ubuntu/miniconda3/lib/python3.11/site-packages (1.7.4)\n",
      "Requirement already satisfied: numba in /home/ubuntu/miniconda3/lib/python3.11/site-packages (0.58.1)\n",
      "Requirement already satisfied: pandas in /home/ubuntu/miniconda3/lib/python3.11/site-packages (2.2.1)\n",
      "Requirement already satisfied: plotly in /home/ubuntu/miniconda3/lib/python3.11/site-packages (5.17.0)\n",
      "Requirement already satisfied: nbformat in /home/ubuntu/miniconda3/lib/python3.11/site-packages (5.9.2)\n",
      "Requirement already satisfied: jinja2 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (3.1.2)\n",
      "Requirement already satisfied: kaleido in /home/ubuntu/miniconda3/lib/python3.11/site-packages (0.2.1)\n",
      "Requirement already satisfied: tqdm in /home/ubuntu/miniconda3/lib/python3.11/site-packages (4.66.2)\n",
      "Requirement already satisfied: scikit-learn in /home/ubuntu/miniconda3/lib/python3.11/site-packages (1.3.1)\n",
      "Requirement already satisfied: scipy in /home/ubuntu/miniconda3/lib/python3.11/site-packages (1.12.0)\n",
      "Requirement already satisfied: matplotlib in /home/ubuntu/miniconda3/lib/python3.11/site-packages (3.8.0)\n",
      "Requirement already satisfied: llvmlite<0.42,>=0.41.0dev0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from numba) (0.41.1)\n",
      "Requirement already satisfied: numpy<1.27,>=1.22 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from numba) (1.26.4)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from pandas) (2.9.0.post0)\n",
      "Requirement already satisfied: pytz>=2020.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from pandas) (2024.1)\n",
      "Requirement already satisfied: tzdata>=2022.7 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from pandas) (2024.1)\n",
      "Requirement already satisfied: tenacity>=6.2.0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from plotly) (8.2.3)\n",
      "Requirement already satisfied: packaging in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from plotly) (23.2)\n",
      "Requirement already satisfied: fastjsonschema in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from nbformat) (2.18.1)\n",
      "Requirement already satisfied: jsonschema>=2.6 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from nbformat) (4.19.1)\n",
      "Requirement already satisfied: jupyter-core in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from nbformat) (5.4.0)\n",
      "Requirement already satisfied: traitlets>=5.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from nbformat) (5.11.2)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from jinja2) (2.1.3)\n",
      "Requirement already satisfied: joblib>=1.1.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from scikit-learn) (1.2.0)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from scikit-learn) (3.2.0)\n",
      "Requirement already satisfied: contourpy>=1.0.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from matplotlib) (1.1.1)\n",
      "Requirement already satisfied: cycler>=0.10 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from matplotlib) (0.12.1)\n",
      "Requirement already satisfied: fonttools>=4.22.0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from matplotlib) (4.43.1)\n",
      "Requirement already satisfied: kiwisolver>=1.0.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from matplotlib) (1.4.5)\n",
      "Requirement already satisfied: pillow>=6.2.0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from matplotlib) (10.1.0)\n",
      "Requirement already satisfied: pyparsing>=2.3.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from matplotlib) (3.1.1)\n",
      "Requirement already satisfied: attrs>=22.2.0 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat) (23.2.0)\n",
      "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat) (2023.7.1)\n",
      "Requirement already satisfied: referencing>=0.28.4 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat) (0.30.2)\n",
      "Requirement already satisfied: rpds-py>=0.7.1 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from jsonschema>=2.6->nbformat) (0.10.6)\n",
      "Requirement already satisfied: six>=1.5 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n",
      "Requirement already satisfied: platformdirs>=2.5 in /home/ubuntu/miniconda3/lib/python3.11/site-packages (from jupyter-core->nbformat) (4.2.0)\n"
     ]
    }
   ],
   "source": [
    "!pip install faiss-cpu numba pandas plotly nbformat jinja2 kaleido tqdm scikit-learn scipy matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "from bench import *\n",
    "import plotly.graph_objects as go"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def speed_chart(df, title):\n",
    "    subtitles = [\n",
    "        f'{n}, recall@1 ~{r*100:.2f}%'\n",
    "        for n, r in zip(df['names'], df['recall_at_one'])\n",
    "    ]\n",
    "    fig = go.Figure(\n",
    "        data=[\n",
    "            go.Bar(name='Add', x=subtitles, y=df['add_per_second']),\n",
    "            go.Bar(name='Search', x=subtitles, y=df['search_per_second']),\n",
    "        ])\n",
    "    fig.update_layout(\n",
    "        width=1000,\n",
    "        height=1000,\n",
    "        barmode='group',\n",
    "        title=dict(\n",
    "            text=title,\n",
    "        ),\n",
    "        legend=dict(\n",
    "            orientation='h',\n",
    "            entrywidth=70,\n",
    "            yanchor='bottom',\n",
    "            y=1.02,\n",
    "            xanchor='right',\n",
    "            x=1,\n",
    "        ),\n",
    "    )\n",
    "    fig.write_image(title + '.png')\n",
    "    return fig"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "from usearch.eval import Dataset\n",
    "data = Dataset.build(\n",
    "    vectors='../../datasets/wiki_1M/base.1M.fbin',\n",
    "    queries='../../datasets/wiki_1M/query.public.100K.fbin',\n",
    "    neighbors='../../datasets/wiki_1M/groundtruth.public.100K.ibin',\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "Operation has been terminated",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[9], line 2\u001b[0m\n\u001b[1;32m      1\u001b[0m eval_default \u001b[38;5;241m=\u001b[39m Evaluation\u001b[38;5;241m.\u001b[39mfor_dataset(data)\n\u001b[0;32m----> 2\u001b[0m results_default \u001b[38;5;241m=\u001b[39m \u001b[43mbench_speed\u001b[49m\u001b[43m(\u001b[49m\u001b[43meval_default\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mjit\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n\u001b[1;32m      3\u001b[0m results_default\n",
      "File \u001b[0;32m~/USearch/python/scripts/bench.py:76\u001b[0m, in \u001b[0;36mbench_speed\u001b[0;34m(eval, connectivity, expansion_add, expansion_search, jit, train)\u001b[0m\n\u001b[1;32m     73\u001b[0m     \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[1;32m     75\u001b[0m \u001b[38;5;66;03m# Time to evaluate:\u001b[39;00m\n\u001b[0;32m---> 76\u001b[0m results \u001b[38;5;241m=\u001b[39m \u001b[43m[\u001b[49m\u001b[38;5;28;43meval\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mindex\u001b[49m\u001b[43m)\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mfor\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mindex\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01min\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mindexes\u001b[49m\u001b[43m]\u001b[49m\n\u001b[1;32m     77\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m pd\u001b[38;5;241m.\u001b[39mDataFrame(\n\u001b[1;32m     78\u001b[0m     {\n\u001b[1;32m     79\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnames\u001b[39m\u001b[38;5;124m\"\u001b[39m: [i\u001b[38;5;241m.\u001b[39mpath \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m indexes],\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     83\u001b[0m     }\n\u001b[1;32m     84\u001b[0m )\n",
      "File \u001b[0;32m~/USearch/python/scripts/bench.py:76\u001b[0m, in \u001b[0;36m<listcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m     73\u001b[0m     \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[1;32m     75\u001b[0m \u001b[38;5;66;03m# Time to evaluate:\u001b[39;00m\n\u001b[0;32m---> 76\u001b[0m results \u001b[38;5;241m=\u001b[39m [\u001b[38;5;28;43meval\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mindex\u001b[49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mfor\u001b[39;00m index \u001b[38;5;129;01min\u001b[39;00m indexes]\n\u001b[1;32m     77\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m pd\u001b[38;5;241m.\u001b[39mDataFrame(\n\u001b[1;32m     78\u001b[0m     {\n\u001b[1;32m     79\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnames\u001b[39m\u001b[38;5;124m\"\u001b[39m: [i\u001b[38;5;241m.\u001b[39mpath \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m indexes],\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     83\u001b[0m     }\n\u001b[1;32m     84\u001b[0m )\n",
      "File \u001b[0;32m~/USearch/python/usearch/eval.py:448\u001b[0m, in \u001b[0;36mEvaluation.__call__\u001b[0;34m(self, index, post_clean)\u001b[0m\n\u001b[1;32m    446\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    447\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m task \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtasks:\n\u001b[0;32m--> 448\u001b[0m         task_result \u001b[38;5;241m=\u001b[39m task_result \u001b[38;5;241m+\u001b[39m \u001b[43mtask\u001b[49m\u001b[43m(\u001b[49m\u001b[43mindex\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    449\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m:\n\u001b[1;32m    450\u001b[0m     \u001b[38;5;28;01mpass\u001b[39;00m\n",
      "File \u001b[0;32m~/USearch/python/usearch/eval.py:330\u001b[0m, in \u001b[0;36mAddTask.__call__\u001b[0;34m(self, index)\u001b[0m\n\u001b[1;32m    328\u001b[0m batch_size: \u001b[38;5;28mint\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvectors\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m    329\u001b[0m old_size: \u001b[38;5;28mint\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlen\u001b[39m(index)\n\u001b[0;32m--> 330\u001b[0m dt, _ \u001b[38;5;241m=\u001b[39m \u001b[43mmeasure_seconds\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mindex\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43madd\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mkeys\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvectors\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    332\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(index) \u001b[38;5;241m==\u001b[39m old_size \u001b[38;5;241m+\u001b[39m batch_size\n\u001b[1;32m    333\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m TaskResult(\n\u001b[1;32m    334\u001b[0m     add_operations\u001b[38;5;241m=\u001b[39mbatch_size,\n\u001b[1;32m    335\u001b[0m     add_per_second\u001b[38;5;241m=\u001b[39mbatch_size \u001b[38;5;241m/\u001b[39m dt,\n\u001b[1;32m    336\u001b[0m )\n",
      "File \u001b[0;32m~/USearch/python/usearch/eval.py:140\u001b[0m, in \u001b[0;36mmeasure_seconds\u001b[0;34m(f)\u001b[0m\n\u001b[1;32m    132\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Simple function profiling decorator.\u001b[39;00m\n\u001b[1;32m    133\u001b[0m \n\u001b[1;32m    134\u001b[0m \u001b[38;5;124;03m:param f: Function to be profiled\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    137\u001b[0m \u001b[38;5;124;03m:rtype: Tuple[float, Any]\u001b[39;00m\n\u001b[1;32m    138\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m    139\u001b[0m a \u001b[38;5;241m=\u001b[39m time_ns()\n\u001b[0;32m--> 140\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mf\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    141\u001b[0m b \u001b[38;5;241m=\u001b[39m time_ns()\n\u001b[1;32m    142\u001b[0m c \u001b[38;5;241m=\u001b[39m b \u001b[38;5;241m-\u001b[39m a\n",
      "File \u001b[0;32m~/USearch/python/usearch/eval.py:330\u001b[0m, in \u001b[0;36mAddTask.__call__.<locals>.<lambda>\u001b[0;34m()\u001b[0m\n\u001b[1;32m    328\u001b[0m batch_size: \u001b[38;5;28mint\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mvectors\u001b[38;5;241m.\u001b[39mshape[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m    329\u001b[0m old_size: \u001b[38;5;28mint\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlen\u001b[39m(index)\n\u001b[0;32m--> 330\u001b[0m dt, _ \u001b[38;5;241m=\u001b[39m measure_seconds(\u001b[38;5;28;01mlambda\u001b[39;00m: \u001b[43mindex\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43madd\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mkeys\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvectors\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[1;32m    332\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(index) \u001b[38;5;241m==\u001b[39m old_size \u001b[38;5;241m+\u001b[39m batch_size\n\u001b[1;32m    333\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m TaskResult(\n\u001b[1;32m    334\u001b[0m     add_operations\u001b[38;5;241m=\u001b[39mbatch_size,\n\u001b[1;32m    335\u001b[0m     add_per_second\u001b[38;5;241m=\u001b[39mbatch_size \u001b[38;5;241m/\u001b[39m dt,\n\u001b[1;32m    336\u001b[0m )\n",
      "File \u001b[0;32m~/USearch/python/usearch/index.py:659\u001b[0m, in \u001b[0;36mIndex.add\u001b[0;34m(self, keys, vectors, copy, threads, log, progress)\u001b[0m\n\u001b[1;32m    620\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21madd\u001b[39m(\n\u001b[1;32m    621\u001b[0m     \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m    622\u001b[0m     keys: KeyOrKeysLike,\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    628\u001b[0m     progress: Optional[ProgressCallback] \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m    629\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Union[\u001b[38;5;28mint\u001b[39m, np\u001b[38;5;241m.\u001b[39mndarray]:\n\u001b[1;32m    630\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"Inserts one or move vectors into the index.\u001b[39;00m\n\u001b[1;32m    631\u001b[0m \n\u001b[1;32m    632\u001b[0m \u001b[38;5;124;03m    For maximal performance the `keys` and `vectors`\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    657\u001b[0m \u001b[38;5;124;03m    :type: Union[int, np.ndarray]\u001b[39;00m\n\u001b[1;32m    658\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[0;32m--> 659\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_add_to_compiled\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    660\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_compiled\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    661\u001b[0m \u001b[43m        \u001b[49m\u001b[43mkeys\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mkeys\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    662\u001b[0m \u001b[43m        \u001b[49m\u001b[43mvectors\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mvectors\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    663\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcopy\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcopy\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    664\u001b[0m \u001b[43m        \u001b[49m\u001b[43mthreads\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mthreads\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    665\u001b[0m \u001b[43m        \u001b[49m\u001b[43mlog\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mlog\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    666\u001b[0m \u001b[43m        \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprogress\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    667\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m~/USearch/python/usearch/index.py:266\u001b[0m, in \u001b[0;36m_add_to_compiled\u001b[0;34m(compiled, keys, vectors, copy, threads, log, progress)\u001b[0m\n\u001b[1;32m    264\u001b[0m     pbar\u001b[38;5;241m.\u001b[39mclose()\n\u001b[1;32m    265\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m--> 266\u001b[0m     \u001b[43mcompiled\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43madd_many\u001b[49m\u001b[43m(\u001b[49m\u001b[43mkeys\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mvectors\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcopy\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcopy\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mthreads\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mthreads\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mprogress\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mprogress\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    268\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m keys\n",
      "\u001b[0;31mRuntimeError\u001b[0m: Operation has been terminated"
     ]
    }
   ],
   "source": [
    "eval_default = Evaluation.for_dataset(data)\n",
    "results_default = bench_speed(eval_default)\n",
    "results_default"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "speed_chart(results_default, 'USearch vs FAISS Speed')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eval_sliced = Evaluation.for_dataset(data, batch_size=256)\n",
    "results_sliced = bench_speed(eval_sliced, jit=True)\n",
    "results_sliced"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "speed_chart(results_sliced, 'USearch vs FAISS Speed with 256 Batch Size')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "eval_clustered = Evaluation.for_dataset(data, clusters=10_000)\n",
    "len(eval_clustered.tasks)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "results_clustered = bench_speed(eval_clustered)\n",
    "results_clustered"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "speed_chart(results_clustered, 'USearch vs FAISS Speed on Clustered Data')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "usearch-test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
